//
// Created by 罗宋汤 on 15/8/29.
// Copyright (c) 2015 CHANJET. All rights reserved.
//

#import "CSPRequestRetryHandler.h"


@interface CSPRequestRetryHandler ()

@property (atomic, assign) BOOL isClockSkewRetried;

@end

@implementation CSPRequestRetryHandler

- (instancetype)initWithMaximumRetryCount:(uint32_t)maxRetryCount {
    if (self = [super init]) {
        _maxRetryCount = maxRetryCount;
    }

    return self;
}

- (BOOL)isClockSkewError:(NSError *)error {
    if ([error.domain isEqualToString:CSPGeneralErrorDomain]) {
        switch (error.code) {
            case CSPGeneralErrorRequestTimeTooSkewed:
            case CSPGeneralErrorInvalidSignatureException:
            case CSPGeneralErrorRequestExpired:
            case CSPGeneralErrorAuthFailure:
            case CSPGeneralErrorSignatureDoesNotMatch:
                return YES;
            default:
                break;
        }
    }

    return NO;
}

- (CSPRequestRetryType)shouldRetry:(uint32_t)currentRetryCount
                             response:(NSHTTPURLResponse *)response
                                 data:(NSData *)data
                                error:(NSError *)error {
    if (!self.isClockSkewRetried && [self isClockSkewError:error]) {
        self.isClockSkewRetried = YES;
        return CSPRequestRetryTypeShouldCorrectClockSkewAndRetry;
    }

    if (currentRetryCount >= self.maxRetryCount) {
        return CSPRequestRetryTypeShouldNotRetry;
    }

    if ([error.domain isEqualToString:NSURLErrorDomain]) {
        switch (error.code) {
            case NSURLErrorCancelled:
            case NSURLErrorBadURL:
            case NSURLErrorNotConnectedToInternet:

            case NSURLErrorSecureConnectionFailed:
            case NSURLErrorServerCertificateHasBadDate:
            case NSURLErrorServerCertificateUntrusted:
            case NSURLErrorServerCertificateHasUnknownRoot:
            case NSURLErrorServerCertificateNotYetValid:
            case NSURLErrorClientCertificateRejected:
            case NSURLErrorClientCertificateRequired:
            case NSURLErrorCannotLoadFromNetwork:
                return CSPRequestRetryTypeShouldNotRetry;

            default:
                return CSPRequestRetryTypeShouldRetry;
        }
    }

    switch (response.statusCode) {
        case 500:
        case 503:
            return CSPRequestRetryTypeShouldRetry;
            break;

        default:
            break;
    }

    return CSPRequestRetryTypeShouldNotRetry;
}

- (NSTimeInterval)timeIntervalForRetry:(uint32_t)currentRetryCount
                              response:(NSHTTPURLResponse *)response
                                  data:(NSData *)data
                                 error:(NSError *)error {
    return pow(2, currentRetryCount) * 100 / 1000;
}

@end
